package com.panovue.dataextraction.reader;

import cn.edu.hfut.dmic.webcollector.model.CrawlDatum;
import cn.edu.hfut.dmic.webcollector.model.CrawlDatums;
import cn.edu.hfut.dmic.webcollector.model.Page;
import cn.hutool.core.io.FileUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.panovue.dataextraction.ReaderUtil;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.File;

@Slf4j
public class CSTReader extends AbstractReader {

    public CSTReader() {
        super("CST", true);
    }

    public CSTReader(String key) {
        super("CST", true);
        this.key = key;

        baseUrl = "https://www.cellsignal.cn/";
        baseDir += key + File.separator + "CST" + File.separator;

        // 设置线程数
        setThreads(5);
        addSeedAndReturn(baseUrl + "/browse?search=" + key).type("list");

        getConf().setExecuteInterval(3000);

        buildDriver(true);

        // 开始爬取
        try {
            start(20);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void visit(Page page, CrawlDatums next) {
        data.set("应用类型", "");
        data.set("种属来源", "");
        data.set("反应种属", "");
        data.set("克隆属性", "");
        data.set("着色样式", "");
        data.set("稀释倍数", "");
        data.set("染色例图，对应的样本信息， 酸碱修复条件", "");
        data.set("参考文献情况", "");
    }

    @MatchType(types = "list")
    public void list(Page page, CrawlDatums next) {
        log.info("url {}", page.url());
        Element element = page.select("section a[href*='/product']").first();
        String href = element.attr("href");
        next.addAndReturn(baseUrl + href).type("details");
    }

    @MatchType(types = "details")
    public void details(Page page, CrawlDatums next) {
        Elements tr = page.select("h3:contains(Product Usage Information)").parents().first().select("tr");
        JSONObject application = new JSONObject();
        for (int i = 1; i < tr.size(); i++) {
            Elements td = tr.get(i).select("td");
            application.set(td.get(0).text(), td.get(1).text());
        }
        data.set("应用类型", application);

        Elements Supporting_Data = page.select("h4:contains(Supporting Data)").parents().first().select("table tbody tr");
        JSONObject supportingData = new JSONObject();
        for (int i = 1; i < Supporting_Data.size(); i++) {
            if (i == 1 || i == 3) {
                Elements td = Supporting_Data.get(i).select("td");
                supportingData.set(td.get(0).text(), td.get(1).text());
            }
        }
        data.set("种属来源|反应种属", supportingData);
        data.set("克隆属性", page.select("h1.title").text());

        Elements imgs = page.select("figure img[data-width='520']");
        JSONObject imgJson = new JSONObject();
        for (Element img : imgs) {
            String figcaption = img.parent().parent().select("figcaption").text();
            String url = "https:" + img.attr("data-lazy");
            String alt = url.substring(url.lastIndexOf("/") + 1);
            imgJson.set(url, figcaption);
            ReaderUtil.saveFile(url, baseDir + "images" + File.separator + alt);
        }
        data.set("染色例图", imgJson);

        JSONObject parse = JSONUtil.parseObj((page.select("script[type='application/ld+json']").first().childNode(0).toString()));
        Integer productID = parse.getInt("productID");

        JSONObject literature = JSONUtil.parseObj(HttpUtil.get("https://public-api.cellsignal.com/citebrick/v1/productCitations/" + productID + "?limit=100&offset=0"));
        JSONObject LiteratureList = new JSONObject();
        for (Object citations : literature.getJSONArray("citations")) {
            JSONObject jsonObject = JSONUtil.parseObj(citations);
            String title = jsonObject.getStr("title");
            String url = "https://www.ncbi.nlm.nih.gov/pubmed/" + jsonObject.getInt("pubmedid");
            LiteratureList.set(title, url);
        }
        data.set("文献列表", LiteratureList);
    }

    @MatchCode(codes = {301, 302, 307})
    public void retry(Page page, CrawlDatums next) {
        CrawlDatum crawlDatum = new CrawlDatum();
        crawlDatum.url(page.location());
        crawlDatum.type(page.matchType("list") ? "list" : "details");
        crawlDatum.key(crawlDatum.getExecuteTime() + page.url());
        next.addAndReturn(crawlDatum);
    }

    @Override
    public void afterStop() {
        if (driver != null) {
            driver.quit();
        }
        FileUtil.writeUtf8String(data.toString(), baseDir + File.separator + key + ".json");
        log.info("CST 数据爬取完成");
    }

    @Override
    public void execute(CrawlDatum datum, CrawlDatums next) throws Exception {
        super.execute(datum, next);
        log.info("url {} code {}", datum.url(), datum.code());
    }

    @Override
    public Reader buildReader(String key) {
        return new CSTReader(key);
    }
}
